package pl.grabar.clinic.client.web.actions.admin.users;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.springframework.beans.factory.annotation.Autowired;

import pl.grabar.clinic.core.dao.Dao;
import pl.grabar.clinic.core.domain.enums.PermissionName;
import pl.grabar.clinic.core.domain.enums.UserType;
import pl.grabar.clinic.core.domain.person.User;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;

@Action("saveUser")
@InterceptorRef("grabarStack")
@Results({ @Result(name = "success", type = "redirectAction", location = "list"), @Result(name = "input", location = "editUser.jsp") })
public class SaveUserAction extends ActionSupport implements Preparable {

	private static final long serialVersionUID = 5808272810843250966L;

	private static final Log LOG = LogFactory.getLog(SaveUserAction.class);

	@Autowired
	private Dao<User> userDao;

	private String passwordMatch;

	private User existingUser;

	private String userId;

	private User user;
	
	private Map<UserType, String> userTypes = new HashMap<>();

	private Map<String, String> possiblePermissions = new HashMap<>();

	@Override
	public void prepare() throws Exception {
		prepareUserData();
		if (StringUtils.isNoneBlank(userId) && NumberUtils.isNumber(userId)) {
			existingUser = userDao.findById(userId);
		}
		user.setUserType(UserType.USER);
	}

	@Override
	public void validate() {
		if (!hasErrors()) {
			if (StringUtils.isNotBlank(userId) && existingUser == null) {
				addActionError(getText("pl.grabar.clinic.client.web.admin.users.actions.no-such-user"));
				LOG.error("Blad walidacji w trakcie zapisu uzytkownika. Uzytkownik o podanym id nie istnieje: " + userId);
			}
		}
	}

	@Override
	public String execute() throws Exception {
		if (existingUser != null) {
			updateUser();
		} else {
			saveUser();
		}
		return SUCCESS;
	}

	private void saveUser() throws Exception {
		user.setUserType(UserType.USER);
		userDao.save(user);
		addActionMessage(getText("pl.grabar.clinic.client.web.admin.users.actions.save.saved", new String[] { user.getFullName() }));
		LOG.info("Dodano uzytkownika o id: " + user.getId() + ":" + user.getFirstName() + ":" + user.getLastName());
	}

	private void updateUser() throws Exception {
		existingUser.setAddress(user.getAddress());
		existingUser.setEmail(user.getEmail());
		existingUser.setFirstName(user.getFirstName());
		existingUser.setLastName(user.getLastName());
		existingUser.setLogin(user.getLogin());
		existingUser.setPassword(user.getPassword());
		existingUser.setPatientIdentifier(user.getPatientIdentifier());
		existingUser.setPermissions(user.getPermissions());
		existingUser.setPhoneNumber(user.getPhoneNumber());

		userDao.update(existingUser);
		addActionMessage(getText("pl.grabar.clinic.client.web.admin.users.actions.save.updated",
				new String[] {existingUser.getFullName()}));
		LOG.info("Zaktualizowano uzytkownika o id: " + existingUser.getId() + ":" + existingUser.getFirstName() + ":" + existingUser.getLastName());

	}

	private void prepareUserData() {
		userTypes.put(UserType.ADMIN, getText("pl.grabar.clinic.client.web.labels.admin"));
		userTypes.put(UserType.DOCTOR, getText("pl.grabar.clinic.client.web.labels.doctor"));
		userTypes.put(UserType.USER, getText("pl.grabar.clinic.client.web.labels.user"));
		userTypes.put(UserType.RECEPTIONIST, getText("pl.grabar.clinic.client.web.labels.receptionist"));

		possiblePermissions.put(PermissionName.ADMIN.toString(), getText(PermissionName.ADMIN.getI18nValue()));
		possiblePermissions.put(PermissionName.DOCTOR.toString(), getText(PermissionName.DOCTOR.getI18nValue()));
		possiblePermissions.put(PermissionName.GUEST.toString(), getText(PermissionName.GUEST.getI18nValue()));
		possiblePermissions.put(PermissionName.PATIENT.toString(), getText(PermissionName.PATIENT.getI18nValue()));
		possiblePermissions.put(PermissionName.RECEPTIONIST.toString(), getText(PermissionName.RECEPTIONIST.getI18nValue()));
	}

	/* AKCESORY */

	public String getPasswordMatch() {
		return passwordMatch;
	}

	public void setPasswordMatch(String passwordMatch) {
		this.passwordMatch = passwordMatch;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public User getExistingUser() {
		return existingUser;
	}

	public void setUserDao(Dao<User> userDao) {
		this.userDao = userDao;
	}

	public Map<UserType, String> getUserTypes() {
		return userTypes;
	}

	public void setUserTypes(Map<UserType, String> userTypes) {
		this.userTypes = userTypes;
	}

	public void setExistingUser(User existingUser) {
		this.existingUser = existingUser;
	}

	public Map<String, String> getPossiblePermissions() {
		return possiblePermissions;
	}

	public void setPossiblePermissions(Map<String, String> possiblePermissions) {
		this.possiblePermissions = possiblePermissions;
	}

}
